package com.openatc.agent.controller;

import com.auth0.jwt.algorithms.Algorithm;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.openatc.agent.config.RestTemplateConfig;
import com.openatc.agent.model.RbacUser;
import com.openatc.agent.model.User;
import com.openatc.agent.service.UserDao;
import com.openatc.agent.utils.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import org.springframework.web.util.UriComponentsBuilder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Calendar;
import java.util.Date;
import java.util.logging.Logger;

/**
 * @author ：zhangwenchao
 * @date ：Created in 2022/11/3 10:16
 * @description：统一权限接口类
 * @modified By：
 * @version: $
 */

@Controller
public class RbacController {

    private Gson gson = new Gson();
    private static Logger logger = Logger.getLogger(UserController.class.toString());

    @Value("${cloud.rbac.baseurl}")
    private String baseurl;
    @Value("${cloud.rbac.client_id}")
    private String client_id;
    @Value("${cloud.rbac.client_secret}")
    private String client_secret;
    @Value("${cloud.rbac.grant_type}")
    private String grant_type;
    @Value("${cloud.rbac.redirect_uri}")
    private String redirect_uri;
    @Autowired
    private TokenUtil tokenUtil;
    @Value("${jwt.token.secret:kedacom}")
    private String secret;
//    @Value("${cloud.rbac.openatc.token:kedacom}")
    private String openatcToken;
    private String bizPage;
    @Autowired
    private UserDao userDao;

    @RequestMapping("/oauth2/cloudrbaurl")
    public ModelAndView getCloudrbaUrl(HttpServletRequest request){

        // http://rbac.devdolphin.com/cloud-rbac/authorize?response_type=code&scope=scope&client_id=jt-iss-back&redirect_uri=http%3A%2F%2F192.168.14.182%3A10003%2Fopenatc%2Foauth2%2Fcallback&return_uri=https%3A%2F%2F127.0.0.1:10003/openatc
//        String urlstr = String.format("%s/authorize?response_type=code&scope=scope&client_id=%s&redirect_uri=%s/oauth2/callback&return_uri=%s",baseurl,client_id,redirect_uri,redirect_uri);

        this.bizPage = request.getParameter("bizPage");
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseurl + "/authorize")
                .queryParam("response_type", "code")
                .queryParam("scope","scope")
                .queryParam("client_id",client_id)
                .queryParam("redirect_uri",redirect_uri + "/oauth2/callback")
                .queryParam("return_uri",redirect_uri);
        String reqUrl = builder.build().encode().toUri().toString();
        logger.info("Request /oauth2/cloudrbaurl :" + reqUrl);

        ModelAndView mv=new ModelAndView(new RedirectView(reqUrl));
        return mv;
    }



    @RequestMapping("/oauth2/callback")
    public void authorizationCodeCallback(HttpServletResponse response, String state, String code, String return_uri) throws Exception{
        // 调用请求 http://dev.ctsp.kedacom/cloud-rbac/access_token
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        RestTemplate restTemplate = new RestTemplate(RestTemplateConfig.generateHttpRequestFactory());

        // /access_token 接口说明 根据授权信息和项目类型，返回用户accessToken和jwtToken等信息；

        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseurl + "/access_token")
                .queryParam("client_id", client_id)
                .queryParam("client_secret",client_secret)
                .queryParam("grant_type",grant_type)
                .queryParam("redirect_uri",redirect_uri + "/oauth2/callback")
                .queryParam("code",code);
        String reqUrl = builder.build().encode().toUri().toString();
        HttpEntity entity = new HttpEntity(null, headers);
        ResponseEntity restResponse = restTemplate.exchange(reqUrl, HttpMethod.POST , entity, String.class);
        logger.warning("/access_token Response: " + restResponse.getBody());


        JsonObject access_token = new JsonParser().parse(restResponse.getBody().toString()).getAsJsonObject();
        String jwt_token_str = null;

        if (access_token.get("code").getAsInt() == 0){
            JsonObject jwt_token = access_token.get("result").getAsJsonObject();
            jwt_token_str = jwt_token.get("jwt_token").getAsString();
        }
        else{
            logger.warning("cloud-rbac Get access_token Error,code: " + access_token.get("code").getAsInt());
            return;
//            return RESTRetUtils.errorObj("9999",restResponse.getBody().toString(),"/access_token",0);
        }

        // 获取jwt_token成功，可以通过jwtToken获取登录信息
        JsonObject request = new JsonObject();
        request.addProperty("jwtToken", jwt_token_str);
        request.addProperty("clientId", client_id);
        request.addProperty("clientSecret", client_secret);
        String reqJsonStr = request.toString();
        entity = new HttpEntity(reqJsonStr, headers);
        restResponse = restTemplate.exchange(baseurl + "/resources/getLoginUserByJwt", HttpMethod.POST , entity, String.class);

        JsonObject login_user = new JsonParser().parse(restResponse.getBody().toString()).getAsJsonObject();

        if (login_user.get("code").getAsInt() == 0){
            JsonObject login_user_result = login_user.get("result").getAsJsonObject();
            JsonObject user = login_user_result.get("user").getAsJsonObject();
            RbacUser rbacUser = gson.fromJson(user, RbacUser.class);
            String username = rbacUser.getUsername();
            logger.warning("cloud-rbac Get user_info : " + username + " , " + rbacUser.getStatus() + " , " + rbacUser.getName() + " , " + rbacUser.getDeptName() + " , " + rbacUser.getPhone());
            User dbUser = userDao.getUserByUserName(username);
            // 数据库中不存在统一平台的用户，创建用户
            if (dbUser == null) {
                User newUser = new User();
                newUser.setUser_name(username);
                newUser.setNick_name("autoCreate");
                newUser.setExt_infos("{}");
                userDao.save(newUser);
                logger.info("Auto create user: " + username);
                // 颁发token
                openatcToken = generateConfigToken(username);
            } else {
                // 没有token则新建，存在token，校验用户名是否一致
                if (!StringUtils.hasLength(openatcToken)) {
                    openatcToken = generateConfigToken(username);
                } else {
                    String oldUserName = tokenUtil.getUsernameFromToken(openatcToken);
                    if (!oldUserName.equals(username)) {
                        openatcToken = generateConfigToken(username);
                    }
                }
            }
//            return RESTRetUtils.successObj(user);
        }
        else{
            logger.warning("cloud-rbac Get user_info Error: " + restResponse);
//            return RESTRetUtils.errorObj("9999",restResponse.getBody().toString(),"/resources/getLoginUserByJwt",0);
        }
        if (bizPage == null) {
            bizPage = "home";
        }
//        response.setHeader("Authorization","kedacom");
        response.sendRedirect(return_uri + "pro/#/" + bizPage + "?token=" + openatcToken);
        logger.info("Request /oauth2/callback: " + return_uri + "pro/#/" + bizPage + "?token=" + openatcToken);

    }

    /**
     * 颁发长期token
     * @return
     */
    private String generateConfigToken(String username) {
        // 10年过期时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.YEAR, 10);
        Date expiration = calendar.getTime();
        // 消除不同服务器1小时内的时间差带来的影响
        Calendar atCalendar = Calendar.getInstance();
        atCalendar.setTime(new Date());

        atCalendar.add(Calendar.HOUR, 0);
        Date issuedAt = atCalendar.getTime();
        Algorithm algorithm = Algorithm.HMAC256(secret);
        String token = tokenUtil.generateToken(username, System.currentTimeMillis(), expiration, issuedAt,algorithm);
        return token;
    }

}
